package com.csw.android.dev_utils.utils

import android.graphics.Color
import android.graphics.PointF
import androidx.annotation.FloatRange
import androidx.annotation.IntRange
import java.lang.Float.max
import java.lang.Float.min

/**
 * CIE XYZ颜色
 *
 * @property x 规格化后的x值[0,1]
 * @property y 规格化后的y值[0,1]
 * @property z 规格化后的z值[0,1]
 */
class CieXYZ(
    val x: Float,
    val y: Float,
    val z: Float,
) {
    companion object {

        /**
         * 通过CIE xyY转化为CIE XYZ
         *
         * @param xPosition x坐标
         * @param yPosition y坐标
         */
        fun fromCIExyY(xPosition: Float, yPosition: Float): CieXYZ {
            return CieXYZ(xPosition, yPosition, 1 - xPosition - yPosition)
        }

        /**
         * 标准rgb转CIE XYZ
         *
         * @param r 红色[0,255]
         * @param g 绿色[0,255]
         * @param b 蓝色[0,255]
         */
        fun fromSRGB(
            @IntRange(from = 0, to = 255) r: Int,
            @IntRange(from = 0, to = 255) g: Int,
            @IntRange(from = 0, to = 255) b: Int
        ) = fromRGB(r / 255f, g / 255f, b / 255f)

        /**
         * RGB颜色转CIE XYZ颜色 [参考](https://blog.51cto.com/u_15341345/3604399)
         *
         * @param red 红色[0,1]
         * @param green 绿色[0,1]
         * @param blue 蓝色[0,1]
         */
        fun fromRGB(
            @FloatRange(from = 0.0, to = 1.0) red: Float,
            @FloatRange(from = 0.0, to = 1.0) green: Float,
            @FloatRange(from = 0.0, to = 1.0) blue: Float
        ): CieXYZ {
            val redLimit = max(0f, min(red, 1f))
            val greenLimit = max(0f, min(green, 1f))
            val blueLimit = max(0f, min(blue, 1f))
            val x = 0.412453f * redLimit + 0.357580f * greenLimit + 0.180423f * blueLimit
            val y = 0.212671f * redLimit + 0.715160f * greenLimit + 0.072169f * blueLimit
            val z = 0.019334f * redLimit + 0.119193f * greenLimit + 0.950227f * blueLimit
            return CieXYZ(
                max(0f, min(x, 1f)),
                max(0f, min(y, 1f)),
                max(0f, min(z, 1f)),
            )
        }
    }

    /**
     * 获取CIE xyY色图坐标
     *
     * @return 色图坐标位置
     */
    fun getCIExyY(): PointF {
        return PointF(x / (x + y + z), y / (x + y + z))
    }

    /**
     * 获取标准rgb色值 [参考](https://blog.51cto.com/u_15341345/3604399)
     * @return [Color]
     */
    fun getSRGB(): Int {
        val red = 3.0799327 * x - 1.537150 * y - 0.542782 * z
        val green = -0.921235 * x + 1.875992 * y + 0.0452442 * z
        val blue = 0.0528909 * x - 0.204043 * y + 1.1511515 * z
        return Color.rgb(
            Integer.max(0, Integer.min(255, (red * 255).toInt())),
            Integer.max(0, Integer.min(255, (green * 255).toInt())),
            Integer.max(0, Integer.min(255, (blue * 255).toInt())),
        )
    }
}